/*
 * @Author: 林子卓 2297304135@qq.com
 * @Date: 2023-11-14 18:27:53
 * @LastEditors: 林子卓 2297304135@qq.com
 * @LastEditTime: 2023-11-15 08:01:23
 * @FilePath: /pipe_text/text.cpp
 * @Description: 管道通信实现
 */

#include <iostream>
#include <string>
#include <cstdio>
#include <unistd.h>
#include <sys/wait.h>
#include <cstring>
#include <sys/types.h>

using namespace std;

const int N = 2;
const int NUM = 1024;

void writer(int wfd)
{
    const string mesg = "hello, I'm child fork";
    int num = 0;
    pid_t id = getpid();
    char buffer[NUM];
    // 告诉读者这是一个字符串，并且起到了清空字符串的作用
    buffer[0] = 0;
    while (true)
    {
        char c = 'c';
        // snprintf(buffer, NUM, "%s-%d-%d", mesg.c_str(), id, num++);
        // write(wfd, buffer, strlen(buffer));
        write(wfd, &c, 1);
        cout << num++;
        cout << endl;
    }
}

void reader(int rfd)
{
    char buffer[NUM];
    while (true)
    {
        // 为什么这里不用将读到的字符数－1
        sleep(50);
        ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);
        // c语言需要，将其当做字符串
        buffer[n] = 0;
        if (n > 0)
            cout << "my get child mesg:[" << getpid() << "]:#" << buffer << endl;
        else
            cout << "没有接收到信息!\n";
    }
}

int main()
{
    int pipefd[N];
    int ret = pipe(pipefd);
    if (ret == -1)
        return 1;
    pid_t id = fork();
    // 实现子进程进行传输信息，父进程接收信息
    if (id == -1)
        return 2;
    if (id == 0)
    {
        // child
        // 为了防止误操作，需要关闭子进程的读端口
        close(pipefd[0]);

        writer(pipefd[1]);

        // 可有可无,因为进程结束文件数据一定会被操作系统回收
        close(pipefd[1]);
    }
    // parent
    // 同样，关闭父进程的写端口
    close(pipefd[1]);

    reader(pipefd[0]);

    close(pipefd[0]);
    return 0;
}